/*notes to Team Cosmic Pi
I just got this working in Cosimo's lab using a TTi TG5011 LXI function generator and a Tektronix TDS2024 scope.
It took a lot of fine tuning to get the right buffer read out, so that the rising edge can be consistently seen in the samples.
The buffer index (i.e. how many buffers back in time you need to go) will definitely change based on the rest of the code, but the principle is here
Don't forget that we're interleaving channels 1 and 2, therefore the nth sample is channel 1 and the n+1th sample is channel 2 etc. and if we're reading out 50, it's actually 25 from channel A etc.
Also note that the ADC seems to top out (4096) around 2.3V, I was expecting 3.3V, so maybe there's another setting to tweak here.

If you are testing this code independently here are your parameters for connection:
Set up a SAW wave, with a vertical rising edge, then monotonically decreasing
Amplitude (max) 2.3V, never above 3.3V or you'll cook the DUE
Frequency - Tested up to 10Hz, our specification max is 5 Hz.
Pinouts:
Saw wave goes in to D2 (trigger), A6 and A7 (ADC channels)

Unexplained - when I hook up one of the ADC inputs to 0V it crashes. I think it might be due to an offset somewhere in the signal generator/earthing mess/laptop USB grounding...
 */

volatile int bufn,obufn,pbufn,qbufn; //obuf, pbuf and qbuf are the previously filled buffers (i.e. going backwards in time)
uint16_t buf[8][256];   // 8 buffers of 256 readings
bool bufferdump=false;  //flag for event, when the buffer should be dumped

void ADC_Handler(){     // move DMA pointers to next buffer
  int f=ADC->ADC_ISR;
  if (f&(1<<27)){
   //memcpy(lastbuf, buf[bufn], 256);
   bufn=(bufn+1)&7;
   ADC->ADC_RNPR=(uint32_t)buf[bufn];
   ADC->ADC_RNCR=256;
  } 
}

void setup(){
  Serial.begin(115200); //serial output at high speed, tested up to 10Hz with this configuration (for a minute or two) 
  //while(!Serial);
  pmc_enable_periph_clk(ID_ADC);
  adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);

  
  REG_ADC_MR = 0x10380080;  // Free run as fast as you can - ADC settings as current core Cosmic Pi code
  REG_ADC_CHER = 3;   // Channels 0 and 1

  NVIC_EnableIRQ(ADC_IRQn);
  ADC->ADC_IDR=~(1<<27);
  ADC->ADC_IER=1<<27;
  ADC->ADC_RPR=(uint32_t)buf[0];   // DMA buffer
  ADC->ADC_RCR=256;
  ADC->ADC_RNPR=(uint32_t)buf[1]; // next DMA buffer
  ADC->ADC_RNCR=256;
  bufn=obufn=1;
  ADC->ADC_PTCR=1;
  ADC->ADC_CR=2;
  TimersStart();
}

//Routine copied out of Cosmic Pi core code, only using one interrupt on Pin 2 for this test.
void TimersStart() {

        uint32_t config = 0;

  // Set up the power management controller for TC0 and TC2

        pmc_set_writeprotect(false);    // Enable write access to power management chip
        pmc_enable_periph_clk(ID_TC0);  // Turn on power for timer block 0 channel 0
        pmc_enable_periph_clk(ID_TC6);  // Turn on power for timer block 2 channel 0

  // Timer block zero channel zero is connected only to the PPS 
  // We set it up to load regester RA on each PPS and reset
  // So RA will contain the number of clock ticks between two PPS, this
  // value should be very stable +/- one tick

        config = TC_CMR_TCCLKS_TIMER_CLOCK1 |        // Select fast clock MCK/2 = 42 MHz
                 TC_CMR_ETRGEDG_RISING |             // External trigger rising edge on TIOA0
                 TC_CMR_ABETRG |                     // Use the TIOA external input line
                 TC_CMR_LDRA_RISING;                 // Latch counter value into RA

        TC_Configure(TC0, 0, config);                // Configure channel 0 of TC0
        TC_Start(TC0, 0);                            // Start timer running

        TC0->TC_CHANNEL[0].TC_IER =  TC_IER_LDRAS;   // Enable the load AR channel 0 interrupt each PPS
        TC0->TC_CHANNEL[0].TC_IDR = ~TC_IER_LDRAS;   // and disable the rest of the interrupt sources
        NVIC_EnableIRQ(TC0_IRQn);                    // Enable interrupt handler for channel 0

  // Timer block 2 channel zero is connected to the OR of the PPS and the RAY event
 
        config = TC_CMR_TCCLKS_TIMER_CLOCK1 |        // Select fast clock MCK/2 = 42 MHz
                 TC_CMR_ETRGEDG_RISING |             // External trigger rising edge on TIOA1
                 TC_CMR_ABETRG |                     // Use the TIOA external input line
                 TC_CMR_LDRA_RISING;                 // Latch counter value into RA
  
  TC_Configure(TC2, 0, config);                // Configure channel 0 of TC2
  TC_Start(TC2, 0);          // Start timer running
 
  TC2->TC_CHANNEL[0].TC_IER =  TC_IER_LDRAS;   // Enable the load AR channel 0 interrupt each PPS
  TC2->TC_CHANNEL[0].TC_IDR = ~TC_IER_LDRAS;   // and disable the rest of the interrupt sources
  NVIC_EnableIRQ(TC6_IRQn);                    // Enable interrupt handler for channel 0

  // Set up the PIO controller to route input pins for TC0 and TC2

  PIO_Configure(PIOC,PIO_INPUT,
          PIO_PB25B_TIOA0,  // D2 Input 
          PIO_DEFAULT);

  PIO_Configure(PIOC,PIO_INPUT,
          PIO_PC25B_TIOA6,  // D5 Input
          PIO_DEFAULT);
}

// Timer chip interrupt handlers try to get time stamps to within 4 system clock ticks

static uint32_t displ = 0;  // Display values in loop

static uint32_t ppsfl = LOW,  // PPS Flag boolean
    rega0 = 0,  // RA reg
    stsr0 = 0,  // Interrupt status register
    ppcnt = 0;  // PPS count

// Handle the PPS interrupt in counter block 0 ISR


void TC0_Handler() {

  // This ISR is connected only to the PPS (Pulse Per Second) GPS event
  // Each time this runs, set the flag to tell the TC6 ISR we have seen it
  // This logic only works if the TC0 handler gets called before the TC6 handler
  // hence the debug flag which I look at with a scope to be sure.
  // I may introduce a small delay line to ensure this is true, so far it is.


  rega0 = TC0->TC_CHANNEL[0].TC_RA; // Read the RA reg (PPS period)
  stsr0 = TC_GetStatus(TC0, 0);     // Read status and clear load bits

  //Custom code for read out of ADC on trigger is here
  bufferdump=true; //set the buffer dump flag
  Serial.println("trigint"); //announce trigger over serial
  Serial.println(rega0); //write out the counter value (how many clock counts since last trigger)
  Serial.print(bufn); //write out the ADC buffer position at the time of the trigger, note that the lab configuration with this code meant the rising edge was 2 buffers back from the one in use.
}


void loop(){
  if (bufferdump) {
    Serial.println(" bufferdump"); //confirm this part of the code is running
  
    //obufn=(bufn+7)&7;  //look in the previous buffer (n-1)
    //pbufn=(bufn+6)&7;  //look in the one before that (n-2)
    qbufn=(bufn+5)&7;  // and look in the buffer before that (n-3)
  
    //SerialUSB.write((uint8_t *)buf[obufn],512); // send it - 512 bytes = 256 uint16_t - this was the original code, converted to serialise and int the buffer for simplicity
    Serial.println("n-2 buffer"); //the buffer index, i.e. qbufn
      for (int s=0; s < 50; s++){
        Serial.print(int(s)); //sample index within buffer
        Serial.print(' ');
        Serial.println(int(buf[qbufn][s])); //print the value from the buffer
      }
    Serial.println();
  
  
    bufferdump = false;//reset flag
    }
  
  }